From: Matthieu Gallien Date: Wed, 29 Jan 2025 13:13:16 +0000 (+0100) Subject: partial fix for broken automated tests X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~2^2~87^2~7 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success/%22http:/www.example.com/cgi/success?a=commitdiff_plain;h=f42c944e6a369e372e652df12474829373b65c4a;p=nextcloud-desktop.git partial fix for broken automated tests will use different validation method for hardware stored certificates and pure software certificates emited by the nextcloud server Signed-off-by: Matthieu Gallien --- diff --git a/src/libsync/clientsideencryption.cpp b/src/libsync/clientsideencryption.cpp index 3f2a8a1d1..5aaa40bf5 100644 --- a/src/libsync/clientsideencryption.cpp +++ b/src/libsync/clientsideencryption.cpp @@ -937,7 +937,9 @@ const QString &ClientSideEncryption::getMnemonic() const void ClientSideEncryption::setCertificate(const QSslCertificate &certificate) { - _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{certificate}}; + _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate, + _encryptionCertificate.getPrivateKeyData(), + QSslCertificate{certificate}}; } const QSslCertificate& ClientSideEncryption::getCertificate() const @@ -1411,7 +1413,9 @@ void ClientSideEncryption::publicCertificateFetched(Job *incoming) return; } - _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{readJob->binaryData(), QSsl::Pem}}; + _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate, + _encryptionCertificate.getPrivateKeyData(), + QSslCertificate{readJob->binaryData(), QSsl::Pem}}; if (_encryptionCertificate.getCertificate().isNull()) { fetchPublicKeyFromKeyChain(account); @@ -2042,7 +2046,9 @@ void ClientSideEncryption::sendSignRequestCSR(const AccountPtr &account, connect(job, &SignPublicKeyApiJob::jsonReceived, job, [this, account, keyPair = std::move(keyPair)](const QJsonDocument& json, const int retCode) { if (retCode == 200) { const auto cert = json.object().value("ocs").toObject().value("data").toObject().value("public-key").toString(); - _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{cert.toLocal8Bit(), QSsl::Pem}}; + _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate, + _encryptionCertificate.getPrivateKeyData(), + QSslCertificate{cert.toLocal8Bit(), QSsl::Pem}}; Bio certificateBio; const auto certificatePem = _encryptionCertificate.getCertificate().toPem(); BIO_write(certificateBio, certificatePem.constData(), certificatePem.size()); @@ -2328,7 +2334,9 @@ void ClientSideEncryption::getPublicKeyFromServer(const AccountPtr &account) connect(job, &JsonApiJob::jsonReceived, [this, account](const QJsonDocument& doc, int retCode) { if (retCode == 200) { QString publicKey = doc.object()["ocs"].toObject()["data"].toObject()["public-keys"].toObject()[account->davUser()].toString(); - _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{publicKey.toLocal8Bit(), QSsl::Pem}}; + _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate, + _encryptionCertificate.getPrivateKeyData(), + QSslCertificate{publicKey.toLocal8Bit(), QSsl::Pem}}; fetchAndValidatePublicKeyFromServer(account); } else if (retCode == 404) { qCDebug(lcCse()) << "No public key on the server"; @@ -3002,22 +3010,34 @@ CertificateInformation::CertificateInformation() CertificateInformation::CertificateInformation(PKCS11_KEY *hardwarePrivateKey, QSslCertificate &&certificate) - : _hardwarePrivateKey(hardwarePrivateKey) - , _certificate(std::move(certificate)) + : _hardwarePrivateKey{hardwarePrivateKey} + , _certificate{std::move(certificate)} + , _certificateType{CertificateType::HardwareCertificate} { checkEncryptionCertificate(); } -CertificateInformation::CertificateInformation(const QByteArray &privateKey, QSslCertificate &&certificate) +CertificateInformation::CertificateInformation(CertificateType certificateType, + const QByteArray &privateKey, + QSslCertificate &&certificate) : _hardwarePrivateKey() , _privateKeyData() , _certificate(std::move(certificate)) + , _certificateType{certificateType} { if (!privateKey.isEmpty()) { setPrivateKeyData(privateKey); } - checkEncryptionCertificate(); + switch (_certificateType) + { + case CertificateType::HardwareCertificate: + checkEncryptionCertificate(); + break; + case CertificateType::SoftwareNextcloudCertificate: + doNotCheckEncryptionCertificate(); + break; + } } bool CertificateInformation::operator==(const CertificateInformation &other) const @@ -3208,4 +3228,12 @@ void CertificateInformation::checkEncryptionCertificate() } } +void CertificateInformation::doNotCheckEncryptionCertificate() +{ + _certificateExpired = false; + _certificateNotYetValid = false; + _certificateRevoked = false; + _certificateInvalid = false; +} + } diff --git a/src/libsync/clientsideencryption.h b/src/libsync/clientsideencryption.h index 0c0966689..75bb149c9 100644 --- a/src/libsync/clientsideencryption.h +++ b/src/libsync/clientsideencryption.h @@ -56,12 +56,18 @@ class ClientSideEncryption; class CertificateInformation { public: + enum class CertificateType { + SoftwareNextcloudCertificate, + HardwareCertificate, + }; + CertificateInformation(); explicit CertificateInformation(PKCS11_KEY *hardwarePrivateKey, QSslCertificate &&certificate); - explicit CertificateInformation(const QByteArray& privateKey, + explicit CertificateInformation(CertificateType certificateType, + const QByteArray& privateKey, QSslCertificate &&certificate); [[nodiscard]] bool operator==(const CertificateInformation &other) const; @@ -99,12 +105,16 @@ public: private: void checkEncryptionCertificate(); + void doNotCheckEncryptionCertificate(); + PKCS11_KEY* _hardwarePrivateKey = nullptr; QByteArray _privateKeyData; QSslCertificate _certificate; + CertificateType _certificateType = CertificateType::SoftwareNextcloudCertificate; + bool _certificateExpired = true; bool _certificateNotYetValid = true; diff --git a/src/libsync/foldermetadata.cpp b/src/libsync/foldermetadata.cpp index fd4ed36ba..8ceb22dd1 100644 --- a/src/libsync/foldermetadata.cpp +++ b/src/libsync/foldermetadata.cpp @@ -557,8 +557,12 @@ void FolderMetadata::initEmptyMetadata() return initEmptyMetadataLegacy(); } qCDebug(lcCseMetadata()) << "Setting up empty metadata v2"; + + const auto certificateType = _account->e2e()->useTokenBasedEncryption() ? + FolderMetadata::CertificateType::HardwareCertificate : FolderMetadata::CertificateType::SoftwareNextcloudCertificate; + if (_isRootEncryptedFolder) { - if (!addUser(_account->davUser(), _account->e2e()->getCertificate())) { + if (!addUser(_account->davUser(), _account->e2e()->getCertificate(), certificateType)) { qCDebug(lcCseMetadata) << "Empty metadata setup failed. Could not add first user."; _account->reportClientStatus(OCC::ClientStatusReportingStatus::E2EeError_GeneralError); return; @@ -1043,7 +1047,9 @@ void FolderMetadata::slotRootE2eeFolderMetadataReceived(int statusCode, const QS initMetadata(); } -bool FolderMetadata::addUser(const QString &userId, const QSslCertificate &certificate) +bool FolderMetadata::addUser(const QString &userId, + const QSslCertificate &certificate, + CertificateType certificateType) { Q_ASSERT(_isRootEncryptedFolder); Q_ASSERT(!certificate.isNull()); @@ -1052,9 +1058,23 @@ bool FolderMetadata::addUser(const QString &userId, const QSslCertificate &certi return false; } - const auto shareUserCertificate = CertificateInformation{{}, QSslCertificate{certificate}}; + auto convertedCertificateType = CertificateInformation::CertificateType::HardwareCertificate; + switch (certificateType) + { + case CertificateType::HardwareCertificate: + convertedCertificateType = CertificateInformation::CertificateType::HardwareCertificate; + break; + case CertificateType::SoftwareNextcloudCertificate: + convertedCertificateType = CertificateInformation::CertificateType::SoftwareNextcloudCertificate; + break; + } + + const auto shareUserCertificate = CertificateInformation{convertedCertificateType, {}, QSslCertificate{certificate}}; if (userId.isEmpty() || certificate.isNull() || !shareUserCertificate.canEncrypt()) { - qCWarning(lcCseMetadata()) << "Could not add a folder user. Invalid userId or certificate."; + qCWarning(lcCseMetadata()) << "Could not add a folder user. Invalid userId or certificate." + << userId + << (certificate.isNull() ? "user certificate is invalid" : "user certificate is valid") + << (shareUserCertificate.canEncrypt() ? "certificate of share receiver user can encrypt" : "certificate of share receiver user cannot encrypt"); return false; } diff --git a/src/libsync/foldermetadata.h b/src/libsync/foldermetadata.h index 34fda88e8..0fee91771 100644 --- a/src/libsync/foldermetadata.h +++ b/src/libsync/foldermetadata.h @@ -93,6 +93,12 @@ public: }; Q_ENUM(FolderType) + enum class CertificateType { + SoftwareNextcloudCertificate, + HardwareCertificate, + }; + Q_ENUM(CertificateType) + FolderMetadata(AccountPtr account, const QString &remoteFolderRoot, FolderType folderType = FolderType::Nested); /* * construct metadata based on RootEncryptedFolderInfo @@ -121,7 +127,7 @@ public: [[nodiscard]] bool moveFromFileDropToFiles(); // adds a user to have access to this folder (always generates new metadata key) - [[nodiscard]] bool addUser(const QString &userId, const QSslCertificate &certificate); + [[nodiscard]] bool addUser(const QString &userId, const QSslCertificate &certificate, CertificateType certificateType); // removes a user from this folder and removes and generates a new metadata key [[nodiscard]] bool removeUser(const QString &userId); diff --git a/src/libsync/updatee2eefolderusersmetadatajob.cpp b/src/libsync/updatee2eefolderusersmetadatajob.cpp index c6bfc07c0..065ace9bc 100644 --- a/src/libsync/updatee2eefolderusersmetadatajob.cpp +++ b/src/libsync/updatee2eefolderusersmetadatajob.cpp @@ -136,8 +136,11 @@ void UpdateE2eeFolderUsersMetadataJob::startUpdate() return; } + const auto certificateType = _account->e2e()->useTokenBasedEncryption() ? + FolderMetadata::CertificateType::HardwareCertificate : FolderMetadata::CertificateType::SoftwareNextcloudCertificate; + const auto result = _operation == Operation::Add - ? _encryptedFolderMetadataHandler->folderMetadata()->addUser(_folderUserId, _folderUserCertificate) + ? _encryptedFolderMetadataHandler->folderMetadata()->addUser(_folderUserId, _folderUserCertificate, certificateType) : _encryptedFolderMetadataHandler->folderMetadata()->removeUser(_folderUserId); if (!result) { diff --git a/test/testclientsideencryptionv2.cpp b/test/testclientsideencryptionv2.cpp index 96ef34ddb..30b98e09f 100644 --- a/test/testclientsideencryptionv2.cpp +++ b/test/testclientsideencryptionv2.cpp @@ -245,11 +245,11 @@ private slots: encryptedFile.initializationVector = EncryptionHelper::generateRandom(16); metadata->addEncryptedFile(encryptedFile); - QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate())); + QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate(), FolderMetadata::CertificateType::SoftwareNextcloudCertificate)); QVERIFY(metadata->removeUser(_secondAccount->davUser())); - QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate())); + QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate(), FolderMetadata::CertificateType::SoftwareNextcloudCertificate)); const auto encryptedMetadata = metadata->encryptedMetadata(); QVERIFY(!encryptedMetadata.isEmpty());